using System;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;
using System.Collections;
using System.ComponentModel;
using System.Text;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;

using SharePointOfView.Utilities;
using SharePointOfView.Properties;

namespace SharePointOfView.WebControls
{
    /// <summary>SharePointOfView framework base WebPart.</summary>
    /// <remarks>Inherits of System.Web.UI.WebControls.WebParts.WebPart</remarks>
    /// <seealso cref="System.Web.UI.WebControls.WebParts.WebPart"/>
    public abstract class WebPartBase : System.Web.UI.WebControls.WebParts.WebPart
    {
        #region Private statements

        private const string resErrorTitleKey = "WebPartBaseErrorTitle";
        private const string resErrorBodyKey = "WebPartBaseErrorBody";

        #endregion

        #region Base sealed methods

        /// <summary>Base method that renders the web part.</summary>
        /// <param name="writer">the output stream Html writer</param>
        protected sealed override void RenderContents(HtmlTextWriter writer)
        {
            try
            {
                base.EnsureChildControls();
                base.RenderContents(writer);
                RenderWebPart(writer);
            }
            catch(Exception ex)
            {
                // Rendering a simple error message instead of the WebPart and logging the real exception
                ManageError(ex).RenderControl(writer);
                SharePointOfView.Diagnostics.ULS.WriteError(ex.ToString(), "WebPartBase : RenderContents");
            }
        }

        /// <summary>Base method that add child controls to the Web Part.</summary>
        protected sealed override void CreateChildControls()
        {
            base.CreateChildControls();

            try
            {
                ScriptLink effectScript = new ScriptLink();
                string scriptUrl = Page.ClientScript.GetWebResourceUrl(this.GetType().BaseType, "SharePointOfView.Resources.SPovErrMgrScript.js");
                if (!Page.ClientScript.IsClientScriptBlockRegistered("SPovErrMgrScript"))
                {
                    Page.ClientScript.RegisterClientScriptInclude("SPovErrMgrScript", scriptUrl);
                }
                this.CreateWebPartControls();
            }
            catch (Exception ex)
            {
                // Rendering a simple error message instead of the WebPart and logging the real exception
                this.Controls.Add(ManageError(ex));
                SharePointOfView.Diagnostics.ULS.WriteError(ex.ToString(), "WebPartBase : CreateChildControls");
            }
        }

        #endregion

        #region Enhanced virtual methods

        /// <summary>
        /// Abstract method that replace RenderContents method, so as to ensure error handling. 
        /// If a failure occurs, a standard message will be shown to the users, and the error will be logged.
        /// Besides, the exact exception stack trace will be displayed to the sites collection administrators.
        /// </summary>
        /// <param name="writer">the output stream Html writer</param>
        protected virtual void RenderWebPart(HtmlTextWriter writer)
        {

        }

        /// <summary>
        /// Abstract method that replace CreateChildControls method, so as to ensure error handling. 
        /// If a failure occurs, a standard message will be shown to the users, and the error will be logged.
        /// Besides, the exact exception stack trace will be displayed to the sites collection administrators.
        /// </summary>
        protected virtual void CreateWebPartControls()
        {

        }

        #endregion

        #region Error handling methods

        /// <summary>Manage any error occuring within the WebPart.</summary>
        /// <param name="ex">Exception to manage</param>
        private Control ManageError(Exception ex)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<div class=\"UserGeneric\">");
            sb.Append(System.DateTime.Now.ToString());
            sb.Append("<br/><span class=\"ms-bold\">");
            sb.Append(Resources.ResourceManager.GetString(resErrorTitleKey));
            sb.Append(" : </span>");
            sb.Append(Resources.ResourceManager.GetString(resErrorBodyKey));

            sb.Append("<br />");
            if (SPContext.Current.Web.CurrentUser.IsSiteAdmin)
            {
                sb.Append("<a href=\"javascript:slide_toggle('WPErr");
                sb.Append(this.ClientID);
                sb.Append("', 'IMGerr");
                sb.Append(this.ClientID);
                sb.Append("');\" title=\"StackTrace\"><img id=\"IMGerr");
                sb.Append(this.ClientID);
                sb.Append("\" src=\"_layouts\\images\\ewr078.gif\" style=\"border:0; vertical-align:middle\" alt=\"ExpandOrCollapse\"></a>&nbsp;<a href=\"javascript:slide_toggle('WPErr");
                sb.Append(this.ClientID);
                sb.Append("', 'IMGerr");
                sb.Append(this.ClientID);
                sb.Append("');\" title=\"StackTrace\">");
                sb.Append(ex.GetType().ToString());
                sb.Append("</a><br><div style=\"height:0px;\"><div id=\"WPErr");
                sb.Append(this.ClientID);
                sb.Append("\" style=\"display:none; position:absolute; word-wrap: break-word\">");
                sb.Append(ex.ToString());
                sb.Append("</div></div>");
            }
            sb.Append("</div>");

            return new LiteralControl(sb.ToString());
        }

        #endregion
    }
}
